<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CHIP-8 Emulator</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f0f0f0;
            display: flex;
            flex-direction: column;
            align-items: center;
            min-height: 100vh;
        }

        .container {
            max-width: 800px;
            width: 100%;
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        h1 {
            text-align: center;
            color: #333;
        }

        .chip8-screen {
            border: 2px solid #333;
            background-color: #000;
            display: grid;
            grid-template-columns: repeat(64, 1fr);
            grid-template-rows: repeat(32, 1fr);
            gap: 1px;
            margin: 20px auto;
            max-width: 640px;
            aspect-ratio: 2/1;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        .pixel {
            background-color: #000;
            transition: background-color 0.05s;
        }

        .pixel.active {
            background-color: #FF0;
        }

        .keyboard {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            gap: 10px;
            margin: 20px auto;
            max-width: 400px;
        }

        .key {
            padding: 15px;
            text-align: center;
            background-color: #4CAF50;
            color: white;
            border-radius: 5px;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            transition: all 0.1s;
        }

        .key.pressed {
            background-color: #2E7D32;
            transform: translateY(2px);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
        }

        .controls {
            margin: 20px auto;
            text-align: center;
        }

        button {
            padding: 10px 20px;
            background-color: #2196F3;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            margin: 0 5px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            transition: background-color 0.1s;
        }

        button:hover {
            background-color: #0D47A1;
        }

        button:active {
            transform: translateY(1px);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
        }

        .status {
            text-align: center;
            margin: 10px 0;
            color: #555;
            font-size: 14px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>CHIP-8 Emulator</h1>
        <div class="status" id="connectionStatus">Connecting to emulator...</div>
        <div class="chip8-screen" id="screen"></div>
        <div class="keyboard">
            <div class="key" data-key="1">1</div>
            <div class="key" data-key="2">2</div>
            <div class="key" data-key="3">3</div>
            <div class="key" data-key="C">C</div>
            <div class="key" data-key="4">4</div>
            <div class="key" data-key="5">5</div>
            <div class="key" data-key="6">6</div>
            <div class="key" data-key="D">D</div>
            <div class="key" data-key="7">7</div>
            <div class="key" data-key="8">8</div>
            <div class="key" data-key="9">9</div>
            <div class="key" data-key="E">E</div>
            <div class="key" data-key="A">A</div>
            <div class="key" data-key="0">0</div>
            <div class="key" data-key="B">B</div>
            <div class="key" data-key="F">F</div>
        </div>
        <div class="controls">
            <button id="resetButton">Reset</button>
            <button id="pauseButton">Pause</button>
        </div>
    </div>

    <script>
        // 配置参数
        const API_BASE_URL = 'http://localhost:8080'; // 后端API地址
        const REFRESH_INTERVAL = 16; // 刷新间隔，约60FPS
        const MAX_CONNECTION_ATTEMPTS = 5;

        // CHIP-8键盘映射（物理键盘到虚拟键的映射）
        const keyMap = {
            // 第一行：1 2 3 C
            '1': 0x1, '2': 0x2, '3': 0x3, 'c': 0xC,
            // 第二行：4 5 6 D
            '4': 0x4, '5': 0x5, '6': 0x6, 'd': 0xD,
            // 第三行：7 8 9 E
            '7': 0x7, '8': 0x8, '9': 0x9, 'e': 0xE,
            // 第四行：A 0 B F
            'a': 0xA, '0': 0x0, 'b': 0xB, 'f': 0xF,
            // 补充：常用映射（如Z键映射为A）
            'z': 0xA // Z键映射到CHIP-8的A键
        };

        // 应用状态
        const appState = {
            isPaused: false,
            connectionAttempts: 0,
            isConnected: false
        };

        // DOM元素
        const screenElement = document.getElementById('screen');
        const pixels = [];
        const connectionStatus = document.getElementById('connectionStatus');

        // 创建屏幕像素
        function initScreen() {
            for (let y = 0; y < 32; y++) {
                for (let x = 0; x < 64; x++) {
                    const pixel = document.createElement('div');
                    pixel.classList.add('pixel');
                    pixel.dataset.x = x;
                    pixel.dataset.y = y;
                    screenElement.appendChild(pixel);
                    pixels.push(pixel);
                }
            }
        }

        // 更新屏幕显示
        function updateScreen(displayData) {
            for (let y = 0; y < 32; y++) {
                for (let x = 0; x < 64; x++) {
                    const index = y * 64 + x;
                    if (displayData[y][x] === 1) {
                        pixels[index].classList.add('active');
                    } else {
                        pixels[index].classList.remove('active');
                    }
                }
            }
        }

        // 发送按键状态到后端并更新UI
        function sendKeyAndUpdateUI(key, pressed) {
            const keyCode = parseInt(key, 16);
            if (!isNaN(keyCode) && keyCode >= 0 && keyCode <= 15) {
                // 更新UI状态
                const keyEl = document.querySelector(`.key[data-key="${key.toUpperCase()}"]`);
                if (keyEl) {
                    if (pressed) {
                        keyEl.classList.add('pressed');
                    } else {
                        keyEl.classList.remove('pressed');
                    }
                }

                // 发送到后端
                fetch(`${API_BASE_URL}/key`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ key: keyCode, pressed: pressed })
                })
                    .catch(error => console.error('Error sending key:', error));
            }
        }


        // 播放声音
        function playSound() {
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const oscillator = audioContext.createOscillator();
            const gainNode = audioContext.createGain();

            oscillator.type = 'square';
            oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // 440Hz音调
            gainNode.gain.setValueAtTime(0.3, audioContext.currentTime); // 音量

            oscillator.connect(gainNode);
            gainNode.connect(audioContext.destination);

            oscillator.start();
            oscillator.stop(audioContext.currentTime + 0.1); // 持续0.1秒
        }

        // 发送按键状态到后端
        function sendKey(key, pressed) {
            const keyCode = parseInt(key, 16);
            if (!isNaN(keyCode) && keyCode >= 0 && keyCode <= 15) {
                fetch(`${API_BASE_URL}/key`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ key: keyCode, pressed: pressed })
                })
                    .catch(error => console.error('Error sending key:', error));
            }
        }


        // 定期获取模拟器显示数据
        function fetchDisplay() {
            if (appState.isPaused) {
                setTimeout(fetchDisplay, REFRESH_INTERVAL);
                return;
            }

            fetch(`${API_BASE_URL}/display`)
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    appState.connectionAttempts = 0;
                    appState.isConnected = true;
                    connectionStatus.textContent = 'Connected to emulator';
                    connectionStatus.style.color = '#4CAF50';

                    console.log('Received display data:', data); // 添加调试日志

                    if (data.needsDraw) {
                        console.log('Updating screen with new display data'); // 添加调试日志
                        updateScreen(data.display);
                        // 发送确认，重置绘制标志
                        fetch(`${API_BASE_URL}/display`, { method: 'POST' });
                    }

                    // 处理声音
                    if (data.soundPlaying) {
                        playSound();
                    }
                })
                .catch(error => {
                    appState.connectionAttempts++;
                    const isFirstError = appState.connectionAttempts === 1;
                    const isMaxAttempts = appState.connectionAttempts >= MAX_CONNECTION_ATTEMPTS;

                    if (isFirstError) {
                        connectionStatus.textContent = 'Connection error, retrying...';
                        connectionStatus.style.color = '#F44336';
                    } else if (isMaxAttempts) {
                        connectionStatus.textContent = 'Max connection attempts reached. Check backend is running.';
                        connectionStatus.style.color = '#F44336';
                    }

                    console.error('Error fetching display:', error);

                    // 指数退避重试策略
                    const retryDelay = Math.min(5000, 200 * Math.pow(2, appState.connectionAttempts));
                    setTimeout(fetchDisplay, retryDelay);
                });
        }



        // 处理屏幕键盘交互
        function setupScreenKeyboard() {
            document.querySelectorAll('.key').forEach(keyEl => {
                const key = keyEl.dataset.key;
                const keyCode = keyMap[key.toLowerCase()];

                if (keyCode !== undefined) {
                    keyEl.addEventListener('mousedown', () => {
                        sendKeyAndUpdateUI(keyCode.toString(16), true);
                    });

                    keyEl.addEventListener('mouseup', () => {
                        sendKeyAndUpdateUI(keyCode.toString(16), false);
                    });

                    keyEl.addEventListener('mouseleave', () => {
                        sendKeyAndUpdateUI(keyCode.toString(16), false);
                    });
                }
            });
        }

        // 处理物理键盘交互
        function setupPhysicalKeyboard() {
            document.addEventListener('keydown', (e) => {
                const key = e.key.toLowerCase();
                const keyCode = keyMap[key];

                if (keyCode !== undefined) {
                    e.preventDefault();
                    sendKeyAndUpdateUI(keyCode.toString(16), true);
                }
            });

            document.addEventListener('keyup', (e) => {
                const key = e.key.toLowerCase();
                const keyCode = keyMap[key];

                if (keyCode !== undefined) {
                    e.preventDefault();
                    sendKeyAndUpdateUI(keyCode.toString(16), false);
                }
            });
        }

        // 设置控制按钮
        function setupControlButtons() {
            // 重置按钮
            document.getElementById('resetButton').addEventListener('click', () => {
                fetch(`${API_BASE_URL}/reset`, { method: 'POST' })
                    .catch(error => console.error('Error resetting emulator:', error));
            });

            // 暂停/继续按钮
            document.getElementById('pauseButton').addEventListener('click', () => {
                appState.isPaused = !appState.isPaused;
                const button = document.getElementById('pauseButton');
                if (appState.isPaused) {
                    button.textContent = 'Resume';
                } else {
                    button.textContent = 'Pause';
                }
            });
        }

        // 初始化应用
        function initApp() {
            initScreen();
            setupScreenKeyboard();
            setupPhysicalKeyboard();
            setupControlButtons();
            fetchDisplay();

            console.log('CHIP-8 emulator frontend initialized');
            console.log(`Connecting to API at ${API_BASE_URL}`);
        }

        // 页面加载完成后初始化
        window.addEventListener('load', initApp);
    </script>
</body>

</html>